#include<stdio.h>
#include<stdlib.h>
#include<string.h>



void insert_char(struct gap_buffer *TEXT_EDITOR,char ch,long long int poz);
void stergere(struct gap_buffer *TEXT_EDITOR,long long int poz);
bool verificare_gap(struct gap_buffer *TEXT_EDITOR);
bool move_gap(struct gap_buffer *TEXT_EDITOR,long long int poz);
bool ok;


void insert_char(struct gap_buffer *TEXT_EDITOR,char ch,long long int poz)
{
	if(verificare_gap(TEXT_EDITOR) && ok )//verificam daca mai avem spatiu in buffer
		poz++;
	//pentru a insera
	ok=move_gap(TEXT_EDITOR,poz);//ajungem cu gap-ul dupa pozitia la care vom insera
	*(*TEXT_EDITOR).head_gap=ch;//se copiaza caracterul la pozitia ceruta
	(*TEXT_EDITOR).head_gap++;//se incrementeaza adresa de inceput a gap-ului
	//adica, acolo unde vom insera urmatorul caracter
	(*TEXT_EDITOR).dim_gap--;
	if(ok)
		(*TEXT_EDITOR).dim_begin++;
	//dimensiunea gap-ului scade cu o unitate
	//dimensiunea celor trei segmente: de inceput,gap-ul si sfarsitul
	//se actualizeaza in functia move_gap
}

//Functia de stergere a unui caracter la o pozitie data
void stergere(struct gap_buffer *TEXT_EDITOR,long long int poz)
{
	bool ok=move_gap(TEXT_EDITOR,poz);
	//mutam gap-ul in fata pozitiei unde vom sterge un caracter
	//gap-ul se muta cu o pozitie mai in fata
	//nu afisam niciodata ceea ce este in gap
	//dim gap-ului creste cu o unitate
	(*TEXT_EDITOR).after_gap++;
	(*TEXT_EDITOR).dim_end--;
	(*TEXT_EDITOR).dim_gap++;
	if(!ok)
		(*TEXT_EDITOR).dim_begin--;
	//scade dimensiunea portiunii aflate in fata gap-ului
}

//functia ce verifica daca mai este loc in gap inainte
//de a face o anumita operatie
bool verificare_gap(struct gap_buffer *TEXT_EDITOR)
{
	if((*TEXT_EDITOR).dim_gap==0)
	{
		//se realoca matricea dinamica cu dublul dimensiunii sale initiale
		//pentru a evita costul realocarilor de mai multe ori,
		//matricile dinamice se realoca cu dimensiune mare de
		//memorie, ceea ce asigura un cost amortizat in timp
		(*TEXT_EDITOR).buffer=(char *)realloc((*TEXT_EDITOR).buffer,sizeof(char)*((*TEXT_EDITOR).DIM*2));

		//inceputul gap-ului va fi la sfarsitul fostului buffer
		//la viitoarele inserari si stergeri gap-ul se va muta singur
		//in interiorul buffer-ului cu ajutorul functiei move_gap()

		(*TEXT_EDITOR).head_gap=(*TEXT_EDITOR).buffer+(*TEXT_EDITOR).DIM;

		//dimensiunea gap-ului va fi jumatate din noua dimensiune
		//alocata

		(*TEXT_EDITOR).dim_gap=(*TEXT_EDITOR).DIM;

		(*TEXT_EDITOR).dim_begin=(*TEXT_EDITOR).DIM;

		(*TEXT_EDITOR).DIM*=2;

//		(*TEXT_EDITOR).after_gap=(*TEXT_EDITOR).buffer+(*TEXT_EDITOR).DIM-1;

		(*TEXT_EDITOR).dim_end=0;

		//partea de inceput va contine vechiul buffer,
		//iar parte sfarsit va avea dimensiunea 0 si va incepe
		//la sfarsitul gap-ului, urmand ca la urmatoarele operatii
		//aceasta sa isi schimbe dimensiunea
		return 1;
	}
	return 0;
}

//mutarea gapp-ului la o pozitie dorita de un utilizator
bool move_gap(struct gap_buffer *TEXT_EDITOR,long long int poz)
 {
	//Verificam in care dintre cele doua segmente se afla pozitia vizata
	//Apoi mutam gap-ul in fata acelei pozitii copiind caracterele
	//din fata gap-ului
	int contor=0;

	if(poz<=(*TEXT_EDITOR).dim_begin)
	{
		while((*TEXT_EDITOR).head_gap!=(*TEXT_EDITOR).buffer+poz)
		{
			(*TEXT_EDITOR).head_gap--;
			(*TEXT_EDITOR).after_gap=(*TEXT_EDITOR).head_gap+(*TEXT_EDITOR).dim_gap;
			*(*TEXT_EDITOR).after_gap=*(*TEXT_EDITOR).head_gap;
			contor++;
			//gap-ul avanseaza spre inceputul vectorului
			//iar cel da-al doilea segment creste si el in acelasi sens
		}
		(*TEXT_EDITOR).dim_begin=poz+1;
		(*TEXT_EDITOR).dim_end=(*TEXT_EDITOR).dim_end + contor;
		return 0;
	}
	else
	{
		while(((*TEXT_EDITOR).head_gap+(*TEXT_EDITOR).dim_gap)!=(*TEXT_EDITOR).buffer+(*TEXT_EDITOR).dim_gap+(poz))
		{
			*(*TEXT_EDITOR).head_gap=*(*TEXT_EDITOR).after_gap;
			(*TEXT_EDITOR).head_gap++;
			(*TEXT_EDITOR).after_gap++;
		/*	if((*TEXT_EDITOR).after_gap>=(*TEXT_EDITOR).buffer+(*TEXT_EDITOR).DIM)
				(*TEXT_EDITOR).after_gap--;*/
			(*TEXT_EDITOR).dim_end--;
			(*TEXT_EDITOR).dim_begin++;
			//aici gap-ul se muta spre sfarsit
		}
		return 1;
	}
	//redimensionarea celor doua parti, aflate intre gap
}